package com.rex.saas.job;

import com.alibaba.fastjson.JSONObject;
import com.rex.saas.db.entity.SaasStrategyTask;
import com.rex.saas.db.entity.SaasStrategyTaskRecord;
import com.rex.saas.enums.ConditionTypeEnum;
import com.rex.saas.service.StrategyTaskService;
import com.rex.saas.utils.CronValidator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class TimeStrategyJob {
    @Autowired
    private StrategyTaskService strategyTaskService;


    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 4, 60,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());

//    @Scheduled(cron = "0 1/1 * * * ?") // 每
    public void createTimeStrategyTask() {
        List<SaasStrategyTask> timeStrategyTasks =strategyTaskService.getTimeStrategyTasks();
        if(CollectionUtils.isEmpty(timeStrategyTasks)){
            return;
        }
        Date now = new Date();
        timeStrategyTasks.forEach(task->{
            String conditions = task.getConditions();
            JSONObject jsonObject = JSONObject.parseObject(conditions);
            String type = jsonObject.getString("type");
            if(StringUtils.isEmpty(type)){
                log.error("任务类型为空, task:{}",task);
                return;
            }
            Date startTime = null;
            Date endTime = null;
            if(ConditionTypeEnum.Timer.getCode().equals(type)){
                String params = jsonObject.getString("params");
                if(StringUtils.isEmpty(params)){
                    log.error("TimeStrategyJob Timer任务params为空, task:{}",task);
                    return;
                }
                JSONObject paramsObj = JSONObject.parseObject(params);
                String cron = paramsObj.getString("cron");
                if(StringUtils.isEmpty(cron)){
                    log.error("TimeStrategyJob Timer任务cron表达式为空, task:{}",task);
                    return;
                }

                startTime = CronValidator.getNextValidTime(cron, now);

            } else if (ConditionTypeEnum.TimeRange.getCode().equals(type)) {
                String params = jsonObject.getString("params");
                if(StringUtils.isEmpty(params)){
                    log.error("TimeStrategyJob TimeRange任务params为空, task:{}",task);
                    return;
                }
                JSONObject paramsObj = JSONObject.parseObject(params);
                String cron = paramsObj.getString("cron");
                if(StringUtils.isEmpty(cron)){
                    log.error("TimeStrategyJob TimeRange任务cron表达式为空, task:{}",task);
                    return;
                }
                startTime = CronValidator.getNextValidTime(cron, now);
                endTime = CronValidator.getNextInvalidTimeAfter(cron, now);
            }

            if(startTime!=null){
                List<SaasStrategyTaskRecord> taskRecords = strategyTaskService.queryActionTaskRecord(task.getId(), startTime);
                if(CollectionUtils.isEmpty(taskRecords)){
                    Long recordId = strategyTaskService.addRecord(startTime, task.getTenantId(), task.getId(), task.getActions());
                    if(recordId==null){
                        log.error("TimeStrategyJob addRecord error, startTime:{}, task:{}", startTime, task);
                    }else {
                        log.info("TimeStrategyJob addRecord success, startTime:{}, task:{}", startTime, task);
                    }
                }
            }
            if(endTime!=null){
                List<SaasStrategyTaskRecord> taskRecords = strategyTaskService.queryRecoverTaskRecord(task.getId(), startTime, endTime);
                if(CollectionUtils.isEmpty(taskRecords)){
                    Long recordId = strategyTaskService.addRecord(endTime, task.getTenantId(), task.getId(), task.getRecovers());
                    if(recordId==null){
                        log.error("TimeStrategyJob addRecord error, endTime：{}, task:{}", endTime, task);
                    }else{
                        log.info("TimeStrategyJob addRecord success, endTime：{}, task:{}", endTime, task);
                    }
                }
            }
        });
        log.info("TimeStrategyJob createTimeStrategyTask end, time：{}", new Date());
    }

//    @Scheduled(cron = "0 */1 * * * ?") // 每
    public void executeTaskRecord() {
        List<SaasStrategyTaskRecord> timeStrategyTasksRecord =strategyTaskService.getTodoStrategyTasksRecord();
        if(!CollectionUtils.isEmpty(timeStrategyTasksRecord)){
            timeStrategyTasksRecord.forEach(task->{
                threadPoolExecutor.submit(()->{
                    boolean result = doTask(task);
                    if(!result){
                        log.error("executeTaskRecord error, task:{}", task);
                    }
                });
            });
        }
//        log.info("TimeStrategyJob executeTaskRecord end, time：{}", new Date());
    }


//    @Scheduled(cron = "0 */1 * * * ?") // 每
    public void refeshTriggerStrategyTask() {
        strategyTaskService.refeshTriggerStrategyTask();
        log.info("TimeStrategyJob refeshTriggerStrategyTask end, time：{}", new Date());
    }


    private boolean doTask(SaasStrategyTaskRecord task) {
        return strategyTaskService.executeTaskRecord(task);
    }
}
